package su.msk.jet.team01.chatik.server.commands;

import su.msk.jet.team01.chatik.server.data.Client;
import su.msk.jet.team01.chatik.server.exception.InvalidArgsCountException;
import su.msk.jet.team01.chatik.server.exception.InvalidArgumentException;

public abstract class Command {

	private static final String EXCEPTION_MSG_ARGUMENT_WITH_SPACES = "Invalid argument format: contain spaces.";
	private static final String EXCEPTION_MSG_INVALID_NUMBER_OF_ARGUMENTS = "Invalid args count given (%s/%s)";
	private static final String EXCEPTION_MSG_INVALID_ARGUMENT_LENGTH = "Argument too long: received %s, maximum %s";

	protected static final int MAX_MESSAGE_LENGTH = 1000;

	private String name;
	private int maxArgsCount;
	private int minArgsCount;

	protected Command(final String name, final int maxArgsCount) {
		this(name, maxArgsCount, maxArgsCount);
	}
	
	protected Command(final String name, final int minArgsCount, final int maxArgsCount) {
		this.name = name;
		this.maxArgsCount = maxArgsCount;
		this.minArgsCount = minArgsCount;
	}

	public abstract void doExecute(Client client, String[] args)
			throws InvalidArgumentException;

	public void execute(final Client client, final String[] args)
			throws InvalidArgsCountException, InvalidArgumentException {
		validateArgsCount(args);
		validateHaveNoEmptyArgs(args);
		doExecute(client, args);
	}

	public int getMaxArgsCount() {
		return maxArgsCount;
	}

	public String getName() {
		return name;
	}

	public void validateArgsCount(final String[] args)
			throws InvalidArgsCountException {
		int length = (args == null ? 0 : args.length);
		if (length > getMaxArgsCount() || length < getMinArgsCount()) {
			throw new InvalidArgsCountException(
					EXCEPTION_MSG_INVALID_NUMBER_OF_ARGUMENTS, args.length,
					getMaxArgsCount());
		}
	}

	private int getMinArgsCount() {
		return minArgsCount;
	}

	public void validateHaveNoEmptyArgs(final String[] args)
			throws InvalidArgumentException {
		for (String str : args) {
			if (str.isEmpty()) {
				throw new InvalidArgumentException(
						EXCEPTION_MSG_INVALID_NUMBER_OF_ARGUMENTS, args.length,
						getMaxArgsCount());
			}
		}
	}

	protected void validateHaveNoSpaces(final String input)
			throws InvalidArgumentException {
		if (input.matches(".*\\s.*")) {
			throw new InvalidArgumentException(
					EXCEPTION_MSG_ARGUMENT_WITH_SPACES);
		}
	}

	protected void validateLength(final String str, final int maxLength)
			throws InvalidArgumentException {
		if (str.length() > maxLength) {
			throw new InvalidArgumentException(
					EXCEPTION_MSG_INVALID_ARGUMENT_LENGTH, str.length(),
					maxLength);
		}
	}
}
